package com.xuexiang.xui_lib.component.textview.supertextview;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentState;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.TextAlignment;
import ohos.agp.utils.TextTool;
import ohos.app.Context;

import com.xuexiang.xui_lib.component.textview.supertextview.adapter.ContainsMap;
import com.xuexiang.xui_lib.component.textview.supertextview.adapter.OfShapeElement;
import com.xuexiang.xui_lib.component.textview.supertextview.adapter.TypedArray;
import com.xuexiang.xui_lib.util.DisplayUtils;

/**
 * 超级按钮  实现shape所有的属性
 *
 * @since 2021-04-08
 */
public class SuperButton extends Button implements Component.ComponentStateChangedListener {
    private static final int STATE_PRESSED_DOWN = 18432;
    private static final int STATE_PRESSED_UP = 2048;

    private static final ContainsMap<Integer> SHAPE_TYPE =
        new ContainsMap.Builder<Integer>(4, ShapeElement.RECTANGLE)
            .put("RECTANGLE", ShapeElement.RECTANGLE)
            .put("OVAL", ShapeElement.OVAL)
            .put("LINE", ShapeElement.LINE)
            .put("ARC", ShapeElement.ARC)
            .build();

    private static final ContainsMap<ShapeElement.Orientation> SHAPE_ORIENTATION =
        new ContainsMap.Builder<ShapeElement.Orientation>(8)
            .put("TOP_BOTTOM", ShapeElement.Orientation.TOP_TO_BOTTOM)
            .put("TR_BL", ShapeElement.Orientation.TOP_RIGHT_TO_BOTTOM_LEFT)
            .put("RIGHT_LEFT", ShapeElement.Orientation.RIGHT_TO_LEFT)
            .put("BR_TL", ShapeElement.Orientation.BOTTOM_RIGHT_TO_TOP_LEFT)
            .put("BOTTOM_TOP", ShapeElement.Orientation.BOTTOM_TO_TOP)
            .put("BL_TR", ShapeElement.Orientation.BOTTOM_LEFT_TO_TOP_RIGHT)
            .put("LEFT_RIGHT", ShapeElement.Orientation.LEFT_TO_RIGHT)
            .put("TL_BR", ShapeElement.Orientation.TOP_LEFT_TO_BOTTOM_RIGHT)
            .build();

    private static final ContainsMap<Integer> GRADIENT_ORIENTATION =
        new ContainsMap.Builder<Integer>(3, -1)
            .put("LINEAR", ShapeElement.LINEAR_GRADIENT_SHADER_TYPE)
            .put("RADIAL", ShapeElement.RADIAL_GRADIENT_SHADER_TYPE)
            .put("SWEEP", ShapeElement.SWEEP_GRADIENT_SHADER_TYPE)
            .build();

    private static final int DEF_TEXT_SIZE = 24;

    private Context mContext;
    private Color defaultColor = new Color(0x20000000);
    private Color defaultSelectorColor = new Color(0x20000000);
    private Color TRANSPARENT = Color.TRANSPARENT;
    private Color solidColor;
    private Color selectorPressedColor;
    private Color selectorDisableColor;
    private Color selectorNormalColor;

    private float cornersRadius;
    private float cornersTopLeftRadius;
    private float cornersTopRightRadius;
    private float cornersBottomLeftRadius;
    private float cornersBottomRightRadius;

    private int strokeWidth;
    private Color strokeColor;

    private float strokeDashWidth;
    private float strokeDashGap;

    private ShapeElement.Orientation gradientOrientation;

    /*private int gradientAngle;
    private int gradientCenterX;
    private int gradientCenterY;
    private int gradientGradientRadius;*/

    private Color gradientStartColor;
    private Color gradientCenterColor;
    private Color gradientEndColor;

    private int gradientType;
    private boolean useSelector;

    private int shapeType;

    private int gravity;

    private boolean enablePressedAlpha = true;

    public SuperButton(Context context) {
        this(context, null);
    }

    public SuperButton(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public SuperButton(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        mContext = context;
        getAttr(attrSet);
        init();
    }

    private void getAttr(AttrSet attrs) {
        TypedArray typedArray = new TypedArray(attrs);
        gravity = typedArray.getInt("sGravity", 0);
        String shapeTypeString = typedArray.get("sShapeType", "RECTANGLE").toUpperCase();
        shapeType = SHAPE_TYPE.get(shapeTypeString);

        // 填充色
        solidColor = typedArray.getColor("sSolidColor", defaultColor);

        // 状态颜色
        selectorPressedColor = typedArray.getColor("sSelectorPressedColor", defaultSelectorColor);
        selectorDisableColor = typedArray.getColor("sSelectorDisableColor", defaultSelectorColor);
        selectorNormalColor = typedArray.getColor("sSelectorNormalColor", defaultSelectorColor);

        // 圆角
        cornersRadius = typedArray.getDimensionPixelSize("sCornersRadius", 0);
        cornersTopLeftRadius = typedArray.getDimensionPixelSize("sCornersTopLeftRadius", 0);
        cornersTopRightRadius = typedArray.getDimensionPixelSize("sCornersTopRightRadius", 0);
        cornersBottomLeftRadius = typedArray.getDimensionPixelSize("sCornersBottomLeftRadius", 0);
        cornersBottomRightRadius = typedArray.getDimensionPixelSize("sCornersBottomRightRadius", 0);

        // 边框线
        strokeWidth = typedArray.getDimensionPixelSize("sStrokeWidth", 0);
        strokeDashWidth = typedArray.getDimensionPixelSize("sStrokeDashWidth", 0);
        strokeDashGap = typedArray.getDimensionPixelSize("sStrokeDashGap", 0);
        strokeColor = typedArray.getColor("sStrokeColor", defaultColor);

        // 梯度方向
        String stringGradientOrientation = typedArray.getString("sGradientOrientation");
        if (!TextTool.isNullOrEmpty(stringGradientOrientation)) {
            gradientOrientation = SHAPE_ORIENTATION.get(stringGradientOrientation);
        }

        // 梯度
       /* gradientAngle = typedArray.getDimensionPixelSize("sGradientAngle", 0);
        gradientCenterX = typedArray.getDimensionPixelSize("sGradientCenterX", 0);
        gradientCenterY = typedArray.getDimensionPixelSize("sGradientCenterY", 0);
        gradientGradientRadius = typedArray.getDimensionPixelSize("sGradientGradientRadius", 0);*/

        // 渐变色
        gradientStartColor = typedArray.getColor("sGradientStartColor", TRANSPARENT);
        gradientCenterColor = typedArray.getColor("sGradientCenterColor", TRANSPARENT);
        gradientEndColor = typedArray.getColor("sGradientEndColor", TRANSPARENT);

        gradientType = GRADIENT_ORIENTATION.get(typedArray.getString("sGradientType"));

        // 使用选择模板
        useSelector = typedArray.getBoolean("sUseSelector", false);
    }

    private void init() {
        setMultipleLine(true);
        setClickable(true);
        setBackground(getBgElement());
        setSGravity();
        initTextSize();
        setComponentStateChangedListener(this);
    }

    private void initTextSize() {
        if (getTextSize() == DEF_TEXT_SIZE) {
            setTextSize(AttrHelper.fp2px(13, getContext()));
        }
    }

    private Element getBgElement() {
        if (useSelector) {
            // 创建正常状态下元素
            OfShapeElement normalElement = new OfShapeElement();
            applyBaseElement(normalElement);
            setOrientationColor(normalElement, selectorNormalColor);
            // 创建选中状态下元素
            OfShapeElement pressedElement = new OfShapeElement();
            applyBaseElement(pressedElement);
            setOrientationColor(pressedElement, selectorPressedColor);
            // 创建不可用状态下元素
            OfShapeElement disabledElement = new OfShapeElement();
            applyBaseElement(disabledElement);
            setOrientationColor(disabledElement, selectorDisableColor);

            StateElement stateElement = new StateElement();
            stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_PRESSED}, pressedElement);
            stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_DISABLED}, disabledElement);
            stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, normalElement);
            return stateElement;
        } else {
            OfShapeElement normalElement = new OfShapeElement();
            applyBaseElement(normalElement);
            setOrientationColor(normalElement, solidColor);
            return normalElement;
        }
    }

    private void applyBaseElement(OfShapeElement element) {
        element.setShape(shapeType);
        if (cornersRadius != 0) {
            element.setCornerRadius(cornersRadius);
        } else {
            element.setCornerRadius(cornersTopLeftRadius, cornersBottomLeftRadius, cornersTopRightRadius, cornersBottomRightRadius);
        }
        element.setStroke(strokeWidth, strokeColor, strokeDashWidth, strokeDashGap);
    }

    /**
     * 是否使用渐变色
     *
     * @return 是否使用渐变色
     */
    private boolean isUseGradientColor() {
        return gradientOrientation != null;
    }

    /**
     * 设置背景颜色
     * 如果设定的有Orientation 就默认为是渐变色的Button，否则就是纯色的Button
     *
     * @param element element
     * @param defaultColor defaultColor
     */
    private void setOrientationColor(OfShapeElement element, Color defaultColor) {
        if (isUseGradientColor()) {
            element.setOrientation(gradientOrientation);
            if (TRANSPARENT.equals(gradientCenterColor)) {
                element.setColors(gradientStartColor, gradientEndColor);
            } else {
                element.setColors(gradientStartColor, gradientCenterColor, gradientEndColor);
            }
            if (gradientType != -1) {
                element.setShaderType(gradientType);
            }
        } else {
            element.setColor(defaultColor);
        }
    }

    /**
     * 设置文字对其方式
     */
    private void setSGravity() {
        switch (gravity) {
            case 0:
                setTextAlignment(TextAlignment.CENTER);
                break;
            case 1:
                setTextAlignment(TextAlignment.START | TextAlignment.VERTICAL_CENTER);
                break;
            case 2:
                setTextAlignment(TextAlignment.END | TextAlignment.VERTICAL_CENTER);
                break;
            case 3:
                setTextAlignment(TextAlignment.TOP | TextAlignment.HORIZONTAL_CENTER);
                break;
            case 4:
                setTextAlignment(TextAlignment.BOTTOM | TextAlignment.HORIZONTAL_CENTER);
                break;
        }
    }

    @Override
    public void onComponentStateChanged(Component component, int state) {
        if (isEnableChangeAlpha()) {
            switch (state) {
                case STATE_PRESSED_DOWN:
                    this.setAlpha(0.7F);
                    break;
                case STATE_PRESSED_UP:
                default:
                    setAlpha(1);
            }
        }
    }

    public void setEnablePressedAlpha(boolean enablePressedAlpha) {
        this.enablePressedAlpha = enablePressedAlpha;
    }

    private boolean isEnableChangeAlpha() {
        return enablePressedAlpha && !useSelector && isEnabled();
    }

    /**
     * 设置Shape类型
     *
     * @param type 类型
     * @return 对象
     */
    public SuperButton setShapeType(int type) {
        this.shapeType = type;
        return this;
    }

    /**
     * 设置文字对其方式
     *
     * @param gravity 对齐方式
     * @return 对象
     */
    public SuperButton setTextGravity(int gravity) {
        this.gravity = gravity;
        return this;
    }

    /**
     * 设置按下的颜色
     *
     * @param color 颜色
     * @return 对象
     */
    public SuperButton setShapeSelectorPressedColor(Color color) {
        this.selectorPressedColor = color;
        return this;
    }

    /**
     * 设置正常的颜色
     *
     * @param color 颜色
     * @return 对象
     */
    public SuperButton setShapeSelectorNormalColor(Color color) {
        this.selectorNormalColor = color;
        return this;
    }

    /**
     * 设置不可点击的颜色
     *
     * @param color 颜色
     * @return 对象
     */
    public SuperButton setShapeSelectorDisableColor(Color color) {
        this.selectorDisableColor = color;
        return this;
    }

    /**
     * 设置填充的颜色
     *
     * @param color 颜色
     * @return 对象
     */
    public SuperButton setShapeSolidColor(Color color) {
        this.solidColor = color;
        return this;
    }

    /**
     * 设置边框宽度
     *
     * @param strokeWidth 边框宽度值
     * @return 对象
     */
    public SuperButton setShapeStrokeWidth(int strokeWidth) {
        this.strokeWidth = (int) vp2px(mContext, strokeWidth);
        return this;
    }

    /**
     * 设置边框颜色
     *
     * @param strokeColor 边框颜色
     * @return 对象
     */
    public SuperButton setShapeStrokeColor(Color strokeColor) {
        this.strokeColor = strokeColor;
        return this;
    }

    /**
     * 设置边框虚线宽度
     *
     * @param strokeDashWidth 边框虚线宽度
     * @return 对象
     */
    public SuperButton setShapeStrokeDashWidth(float strokeDashWidth) {
        this.strokeDashWidth = vp2px(mContext, strokeDashWidth);
        return this;
    }

    /**
     * 设置边框虚线间隙
     *
     * @param strokeDashGap 边框虚线间隙值
     * @return 对象
     */
    public SuperButton setShapeStrokeDashGap(float strokeDashGap) {
        this.strokeDashGap = vp2px(mContext, strokeDashGap);
        return this;
    }

    /**
     * 设置圆角半径
     *
     * @param radius 半径
     * @return 对象
     */
    public SuperButton setShapeCornersRadius(float radius) {
        this.cornersRadius = vp2px(mContext, radius);
        return this;
    }

    /**
     * 设置左上圆角半径
     *
     * @param radius 半径
     * @return 对象
     */
    public SuperButton setShapeCornersTopLeftRadius(float radius) {
        this.cornersTopLeftRadius = vp2px(mContext, radius);
        return this;
    }

    /**
     * 设置右上圆角半径
     *
     * @param radius 半径
     * @return 对象
     */
    public SuperButton setShapeCornersTopRightRadius(float radius) {
        this.cornersTopRightRadius = vp2px(mContext, radius);
        return this;
    }

    /**
     * 设置左下圆角半径
     *
     * @param radius 半径
     * @return 对象
     */
    public SuperButton setShapeCornersBottomLeftRadius(float radius) {
        this.cornersBottomLeftRadius = vp2px(mContext, radius);
        return this;
    }

    /**
     * 设置右下圆角半径
     *
     * @param radius 半径
     * @return 对象
     */
    public SuperButton setShapeCornersBottomRightRadius(float radius) {
        this.cornersBottomRightRadius = vp2px(mContext, radius);
        return this;
    }

    private float vp2px(Context context, float vp) {
        return DisplayUtils.vp2px(context, vp);
    }

    /**
     * 设置背景渐变方式
     *
     * @param gradientOrientation 渐变类型
     * @return 对象
     */
    public SuperButton setShapeGradientOrientation(ShapeElement.Orientation gradientOrientation) {
        this.gradientOrientation = gradientOrientation;
        return this;
    }

    /**
     * 设置渐变中心X
     *
     * @param gradientCenterX 中心x
     * @return 对象
     */
    public SuperButton setShapeGradientCenterX(int gradientCenterX) {
//        this.gradientCenterX = gradientCenterX;
        return this;
    }

    /**
     * 设置渐变中心Y
     *
     * @param gradientCenterY 中心y
     * @return 对象
     */
    public SuperButton setShapeGradientCenterY(int gradientCenterY) {
//        this.gradientCenterY = gradientCenterY;
        return this;
    }

    /**
     * 设置渐变半径
     *
     * @param gradientGradientRadius 渐变半径
     * @return 对象
     */
    public SuperButton setShapeGradientGradientRadius(int gradientGradientRadius) {
//        this.gradientGradientRadius = gradientGradientRadius;
        return this;
    }

    /**
     * 设置渐变开始的颜色
     *
     * @param gradientStartColor 开始颜色
     * @return 对象
     */
    public SuperButton setShapeGradientStartColor(Color gradientStartColor) {
        this.gradientStartColor = gradientStartColor;
        return this;
    }

    /**
     * 设置渐变中间的颜色
     *
     * @param gradientCenterColor 中间颜色
     * @return 对象
     */
    public SuperButton setShapeGradientCenterColor(Color gradientCenterColor) {
        this.gradientCenterColor = gradientCenterColor;
        return this;
    }

    /**
     * 设置渐变结束的颜色
     *
     * @param gradientEndColor 结束颜色
     * @return 对象
     */
    public SuperButton setShapeGradientEndColor(Color gradientEndColor) {
        this.gradientEndColor = gradientEndColor;
        return this;
    }

    /**
     * 设置渐变类型
     *
     * @param gradientType 类型
     * @return 对象
     */
    public SuperButton setShapeGradientType(int gradientType) {
        this.gradientType = gradientType;
        return this;
    }

    /**
     * 是否使用selector
     *
     * @param useSelector true  or  false
     * @return 对象
     */
    public SuperButton setShapeUseSelector(boolean useSelector) {
        this.useSelector = useSelector;
        return this;
    }

    /**
     * 使用shape
     * 所有与shape相关的属性设置之后调用此方法才生效
     */
    public void setUseShape() {
        init();
    }
}
